package com.ruibang.glass.produce.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.produce.constant.Constants;
import com.ruibang.glass.produce.constant.ProduceErrorCode;
import com.ruibang.glass.produce.domain.req.DeviceReq;
import com.ruibang.glass.produce.domain.resp.Monitor;
import com.ruibang.glass.produce.domain.resp.MonitorPointBase;
import com.ruibang.glass.produce.domain.resp.MonitorRuleResp;
import com.ruibang.glass.produce.entity.Device;
import com.ruibang.glass.produce.entity.MonitorPoint;
import com.ruibang.glass.produce.entity.MonitorRule;
import com.ruibang.glass.produce.entity.RuleBase;
import com.ruibang.glass.produce.mapper.DeviceMapper;
import com.ruibang.glass.produce.service.*;
import com.teaming.cloud.framework2.common.exception.ServiceException;
import com.teaming.cloud.framework2.common.model.ResultBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * @Author: songJinKang
 * @CreateTime: 2023-11-15  09:17
 * @Description: TODO
 * @Version: 1.0
 */
@Slf4j
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {

    @Autowired
    private MonitorPointService monitorPointService;

    @Autowired
    private RuleBaseService ruleBaseService;

    @Autowired
    private MonitorRuleService monitorRuleService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private Sequence sequence;


    /***
     * 新增实体
     * @param device
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultBody addDevice(Device device) {
        if (device == null) {
            return ResultBody.fail(ProduceErrorCode.PARAM_IS_EMPTY.getCode(), ProduceErrorCode.PARAM_IS_EMPTY.getMsg());
        }

        //默认为运行
        device.setStatus(Constants.ONE_STR);

        //保存
        this.save(device);


        //保存规则信息
        List<RuleBase> ruleBases = device.getRuleBases();
        if (CollectionUtils.isNotEmpty(ruleBases)) {
            for (RuleBase ruleBase : ruleBases) {
                ruleBase.setDeviceId(device.getDeviceId());
            }
            ruleBaseService.saveBatch(ruleBases);
        }


        //设置监测点信息
        List<MonitorPoint> monitorPoints = device.getMonitorPoints();
        if (CollectionUtils.isNotEmpty(monitorPoints)) {
            for (MonitorPoint monitorPoint : monitorPoints) {
                monitorPoint.setDeviceId(device.getDeviceId());
                monitorPoint.setCreateTime(LocalDateTime.now());
                monitorPoint.setStatus(Constants.ONE_INT);
            }
            //保存监测点
            monitorPointService.saveBatch(monitorPoints);
            //保存监测点与规则关联信息
            saveMonitorRule(monitorPoints);
        }


        return ResultBody.success();
    }


    /**
     * @Description: 修改设备
     * @version v1.0
     * @author songJinKang
     * @date 2023-11-15 10:41
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultBody modifyDevice(Device device) {
        if (device == null || StringUtils.isBlank(device.getDeviceId())) {
            return ResultBody.fail(ProduceErrorCode.PARAM_IS_EMPTY.getCode(), ProduceErrorCode.PARAM_IS_EMPTY.getMsg());
        }

        //更新设备
        this.updateById(device);

        //处理监测点信息
        List<MonitorPoint> monitorPoints = device.getMonitorPoints();
        if (CollectionUtils.isNotEmpty(monitorPoints)) {
            //删除监测点
            if (CollectionUtils.isNotEmpty(device.getDeleteMonitorIds())) {
                monitorPointService.removeByIds(device.getDeleteMonitorIds());
            }
            //修改、保存
            for (MonitorPoint monitorPoint : monitorPoints) {
                monitorPoint.setDeviceId(device.getDeviceId());
                monitorPoint.setUpdateTime(LocalDateTime.now());
            }
            monitorPointService.saveOrUpdateBatch(monitorPoints);
            //处理监测点规则
            monitorRuleService.removeByDeviceId(device.getDeviceId());
            saveMonitorRule(monitorPoints);
        }

        //处理规则信息
        List<RuleBase> ruleBases = device.getRuleBases();
        if (CollectionUtils.isNotEmpty(ruleBases)) {
            //修改、保存
            ruleBaseService.saveOrUpdateBatch(ruleBases);
            //删除的规则
            if (CollectionUtils.isNotEmpty(device.getDeleteRuleIds())) {
                ruleBaseService.removeByIds(device.getDeleteRuleIds());
            }
        }

        return ResultBody.success();
    }

    private void saveMonitorRule(List<MonitorPoint> monitorPoints) {
        List<MonitorRule> monitorRules = new ArrayList<>();
        for (MonitorPoint monitorPoint : monitorPoints) {
            List<String> ruleIds = monitorPoint.getRuleIds();
            if (CollectionUtils.isNotEmpty(ruleIds)) {
                for (String ruleId : ruleIds) {
                    MonitorRule monitorRule = new MonitorRule();
                    monitorRule.setRuleId(ruleId);
                    monitorRule.setMonitorId(monitorPoint.getMonitorId());
                    monitorRule.setDeviceId(monitorPoint.getDeviceId());
                    monitorRules.add(monitorRule);
                }
            }
        }
        if (monitorRules.size() > 0) {
            monitorRuleService.saveBatch(monitorRules);
        }
    }

    /***
     * 获取设备详情
     * @param deviceId
     * @return
     */
    @Override
    public ResultBody getDetail(String deviceId) {
        if (StringUtils.isBlank(deviceId)) {
            return ResultBody.fail(ProduceErrorCode.PARAM_IS_EMPTY.getCode(), ProduceErrorCode.PARAM_IS_EMPTY.getMsg());
        }

        Device device = baseMapper.getByDeviceId(deviceId);

        if (device != null && StringUtils.isNotBlank(device.getDeviceId())) {
            //设置规则信息
            List<RuleBase> ruleBases = ruleBaseService.getRuleBaseByDeviceId(deviceId);
            device.setRuleBases(ruleBases);

            //设置监测点信息
            List<MonitorPoint> monitorPoints = monitorPointService.queryMonitorPoints(deviceId);
            if (CollectionUtils.isNotEmpty(monitorPoints)) {
                //设置监测点规则信息
                List<String> monitorIds = monitorPoints.stream().map(MonitorPoint::getMonitorId).collect(toList());
                List<MonitorRuleResp> monitorRuleResp = monitorRuleService.getRuleByMonitorId(monitorIds);
                if (CollectionUtils.isNotEmpty(monitorRuleResp)) {
                    Map<String, List<MonitorRuleResp>> monitorRuleRespMap = monitorRuleResp.stream().collect(Collectors.groupingBy(MonitorRuleResp::getMonitorId));
                    for (MonitorPoint monitorPoint : monitorPoints) {
                        List<MonitorRuleResp> monitorRuleResps = monitorRuleRespMap.get(monitorPoint.getMonitorId());
                        if (CollectionUtils.isNotEmpty(monitorRuleResps)) {
                            monitorPoint.setMonitorRuleResp(monitorRuleResps);
                            List<String> ruleIds = monitorRuleResps.stream().map(MonitorRuleResp::getRuleId).collect(toList());
                            monitorPoint.setRuleIds(ruleIds);
                        }
                    }
                }
                device.setMonitorPoints(monitorPoints);
            }

            //
        }
        return ResultBody.success(device);
    }

    /**
     * @Description: 获取设备列表信息
     * @version v1.0
     * @author songJinKang
     * @date 2023/04/10 10:39
     */
    @Override
    public ResultBody queryDevices(DeviceReq deviceReq) {

        List<Device> data = baseMapper.queryDevices(deviceReq);

        //设置监测点信息
        if (CollectionUtils.isNotEmpty(data)) {
            List<String> deviceIds = data.stream().map(Device::getDeviceId).collect(toList());
            List<MonitorPoint> monitorPoints = monitorPointService.getMonitorPointByDeviceId(deviceIds);
            if (CollectionUtils.isNotEmpty(monitorPoints)) {
                //设置监测点实时值
                Map<String, List<MonitorPoint>> monitorPointsMap = monitorPoints.stream().collect(Collectors.groupingBy(MonitorPoint::getDeviceId));
                for (Device device : data) {
                    //获取监测点实时数据
                    String key = String.format(Constants.DEVICE_MAPPING_MONITOR_CACHE, device.getDeviceId());
                    List<Object> objList = redisTemplate.opsForHash().values(key);
                    Map<String, Monitor> monitorDataMap = null;
                    if (CollectionUtils.isNotEmpty(objList)) {
                        List<Monitor> monitors = JSONObject.parseArray(objList.toString(), Monitor.class);
                        monitorDataMap = monitors.stream().collect(Collectors.toMap(Monitor::getMonitorId, e -> e));

                    }
                    //设置监测点数据
                    List<MonitorPointBase> monitorPointBases = new ArrayList<>();
                    List<MonitorPoint> monitorDum = monitorPointsMap.get(device.getDeviceId());

                    if (CollectionUtils.isNotEmpty(monitorDum)) {
                        for (MonitorPoint monitorPoint : monitorDum) {
                            MonitorPointBase monitorPointBase = new MonitorPointBase();
                            monitorPointBase.setMonitorId(monitorPoint.getMonitorId());
                            monitorPointBase.setMonitorName(monitorPoint.getMonitorName());
                            monitorPointBase.setMonitorCode(monitorPoint.getMonitorCode());
                            monitorPointBase.setDeviceId(monitorPoint.getDeviceId());
                            monitorPointBase.setUnit(monitorPoint.getUnit());
                            monitorPointBase.setModulus(monitorPoint.getModulus());
                            monitorPointBase.setCalc(monitorPoint.getCalc());
                            if (monitorDataMap != null) {
                                Monitor monitorData = monitorDataMap.get(monitorPoint.getMonitorId());
                                if (monitorData != null) {
                                    monitorPointBase.setCollectTime(monitorData.getCollectTime());
                                    monitorPointBase.setValue(monitorData.getValue());
                                }
                            }
                            monitorPointBases.add(monitorPointBase);
                        }
                    }

                    if (CollectionUtils.isNotEmpty(monitorPointBases)) {
                        device.setMonitorPointBase(monitorPointBases);
                    }
                }
            }
        }
        return ResultBody.success(data);
    }


    @Override
    public IPage<Device> queryDevicesForPc(DeviceReq deviceReq) {
        return baseMapper.queryDevicesForPc(new Page<>(deviceReq.getPageNo(), deviceReq.getPageSize()), deviceReq);
    }

    @Override
    public Long getUUID() {
        return sequence.nextId();
    }

    @Override
    public List<Device> getDeviceByIds(List<String> deviceIds) {
        return lambdaQuery().in(Device::getDeviceId, deviceIds).list();
    }

    /***
     * 删除设备信息
     * @param deviceId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultBody deleteById(String deviceId) {
        if (StringUtils.isNotBlank(deviceId)) {
            long count = monitorPointService.getCountByDeviceId(deviceId);
            if (count > 0) {
                throw new ServiceException(ProduceErrorCode.MONITOR_POINT_IS_EXIST.getCode(), ProduceErrorCode.MONITOR_POINT_IS_EXIST.getMsg());
            }
            //删除设备
            this.removeById(deviceId);
            //删除规则
            ruleBaseService.removeByDeviceId(deviceId);
            //删除监测点
            monitorPointService.deleteByDeviceId(deviceId);
            //删除监测点规则
            monitorRuleService.removeByDeviceId(deviceId);
        }
        return ResultBody.success();
    }


}
